#include <tabia.h>
#include <stdio.h>
#include <string.h>
#include <delay.h>

#define START_MSG_LENGTH 179 // GLITCH OCCURS AT 101 when connected to AVRISP2, appears to restart micro, reset?
#define GPS_START_MSGS_QUIET 3
#define NOVATEL_SPEED_MSG_CHAR 64 // NovAtel uses @(64): Go to NMEA @19200 baud. 
#define NMEA_MSG_START_CHAR 36 // NovAtel uses $(36)
#define POLLING_TIMEOUT 30000 // timeout in 100us

extern unsigned char twi_tx_counter;

void GPS_init_write(unsigned char mode) 
{
if (mode == 0)
    {
    printf("$PMCAG,005,1,GGA,000\r\n"); // from NMEA, stop GGA transmission
    }

else if (mode == 96)
    {
    printf("$PMCAG,005,9.6,GGA,999\r\n"); // set 9600 bps, set GPGGA, max rate (1 Hz)
    }

else if (mode == 192)
    {
    printf("$PMCAG,005,19.2,GGA,999\r\n"); // set 19200 bps, set GPGGA, max rate (1 Hz)
    }

else if (mode == 1)
    {
    printf("%c%c%c%c%c%c%c", 1, 110, 145, 1, 64, 65, 1); // from binary, set NMEA, 19200 bps
//    UBRR1L=0x31; // set USART1 to 19200 bps
    }

else if (mode == 2)
    {
    printf("$PMCAG,007,15\r\n"); // from NMEA, set binary 9600 bps
    }

else if (mode == 3)
    {
    printf("$PMCAG,007,14\r\n"); // from NMEA, clear NMEA message list from NVM, reset to default on next start (GGA 1 Hz)
    }

else if (mode == 4)
    {
    printf("$PMCAG,005,1,GGA,999\r\n"); // from NMEA, set GPGGA, 5 Hz, store to NVM
    }
}

void GPS_init_read(unsigned char mode) // mode 0: receive only, mode 1: receive and display
{
unsigned char GPS_start_chars = 0;
unsigned char poll_char, i, speed_str[14];
unsigned int speed, char_time;

GPS_init_write(0); // only affects warm start, stopping NMEA message

//#asm("cli")
delay_ms(20); // allow USART1 time to empty (at least 10ms), more than 70ms risks missing front of start message
//#asm("sei")

UBRR1L = 0x63; // set USART1 speed to startup (9600 bps)

//#asm("cli")
delay_ms(100); // allow LCD time to start
//#asm("sei")

LCD_light_on();
    
do
    {
    char_time = POLLING_TIMEOUT;

//    while(twi_tx_counter);

    poll_char = getchar_timed(&char_time);
//    poll_char = getchar();

    if (char_time > 0)
        {
        GPS_start_chars++;

//        LCD_char_write((GPS_start_chars&0x1F) + 64);
//        LCD_char_write(((twi_tx_counter>>4)&0x1F) + 64);
                   
        if (mode)
            {
            if (poll_char == 0)
                {
                poll_char = BUFFER_END_OF_FIELD;
                }
        
            LCD_char_write(poll_char);
            }
        }
//    } while ((poll_char != NOVATEL_SPEED_MSG_CHAR) && (GPS_start_chars < START_MSG_LENGTH) && (char_time > 0));
    } while ((poll_char != NOVATEL_SPEED_MSG_CHAR) && (char_time > 0));

//if ((poll_char != NOVATEL_SPEED_MSG_CHAR) || (GPS_start_chars != START_MSG_LENGTH)) // warm start or startup glitch
if (char_time == 0) // warm start or no internal receiver present
    {
    LCD_reset();
    warm_start_message();
    locate_GPS_message();
    UBRR1L = 0x31; // set speed to default (19200 bps), warm start applies to debug only
    GPS_init_write(192);
    
    do
        {
        char_time = POLLING_TIMEOUT;
        poll_char = getchar_timed(&char_time);
        
        if (char_time == 0) // no internal receiver present
            {
            no_internal_GPS_message();
            poll_char = 0;
            }
        
        if (mode)
            {
            if (poll_char == BUFFER_END_OF_FIELD)
                {
                poll_char = GPS_END_OF_FIELD;
                }
                
            LCD_char_write(poll_char);
            }
        } while (poll_char);
    }

else // read speed, set USART1
    {
    scanf("%u baud.", &speed);

    if (mode)
        {
        sprintf(speed_str, "%c%c%u baud.", LCD_W, STR, speed);
        send_twi_msg(speed_str, strlen(speed_str) + 1);
        }
    
    UBRR1L = (unsigned char)(USART_FUNDAMENTAL/speed) - 1; // set USART1 speed

    //#asm("cli")
    delay_ms(1000);
    //#asm("sei")
    
    GPS_init_write((unsigned char)(speed/100));
        
    do // finish boot screen
        {
        poll_char = getchar();

        if (mode)
            {
            if (poll_char == 0)
                {
                poll_char = BUFFER_END_OF_FIELD;
                }
        
            LCD_char_write(poll_char);
            }
        } while (poll_char != NMEA_MSG_START_CHAR);
    }

for (i = 0; i < GPS_START_MSGS_QUIET; i++)
    {
    do
        {
        char_time = POLLING_TIMEOUT;
        poll_char = getchar_timed(&char_time);

        if (char_time == 0)
            {
            poll_char = 0;
            i = GPS_START_MSGS_QUIET;
            }
        } while (poll_char);
    }

LCD_reset();
}